using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Security.Policy;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.Win32;
using Microsoft.SharePoint.Administration;

namespace SPVisualDev
{
    internal class Common
    {
		public const string C_MS_SHAREPOINT_XMLNS = "http://schemas.microsoft.com/sharepoint/";
		public const string C_MS_SHAREPOINT_EVENTS_NS = "http://schemas.microsoft.com/sharepoint/events";
        public const string C_PROJECT_EVENT_RECEIVER_CODE_PATH = "EventReceivers";
        public const string C_PROJECT_WEB_PART_CODE_PATH = "UI\\WebParts";

        public const string C_GLOBAL_CONFIG_KEY_PREFIX = "SPVisualDev_";
        public const string C_PROJECT_ID_VAR_NAME = "SPVisualDev_ProjID";
        public const string C_SHAREPOINT_ARTIFACTS_PROJECT_ID = "SharePointArtifactsProject";
        public const string C_PROJECT_BUILD_ACTION = "SPVisualDev_ProjBuildAction";
        public const string C_SETTINGS_FILE = "projsettings.xml";
        public const string C_DEFAULT_TARGET_URL = "http://localhost";
        public const string C_DEFAULT_SP_MANAGED_PATH = "SPVisualDev";
        public const string C_IGNORE_FILE_TYPE_ON_PUSH_DOWN = ".cs;.vb";
        public const string C_SPDEVEXTENSIONS_ASSEMBLY_NAME = "SPDevExtensions, Version=1.0.0.1, Culture=neutral, PublicKeyToken=383c1a4a7bd8f1f3";
        public const string C_SPDEVEXTENSIONS_WSSTES_FEATURE_RECEIVER_CLASS = "SPDevExtensions.WSSTES.WSSFeatureReceiverBase";
        public const string C_SPDEVEXTENSIONS_FEATURE_PROPERTY_NAME = "WSSTES_AssemblyToLoad";
        public const string C_LOCAL_RESOURCE_IDENTIFIER = "_Res";

        public static bool RefreshFeatureFile(ProjectItem FeatureFolder)
        {
            try
            {
                FeatureManager manager = new FeatureManager(FeatureFolder);
                manager.ReadContent();
                manager.WriteContent(false);

                return true;
            }
            catch
            {
                return false;
            }
        }

        public static string[] RefreshEventReceivers(string FeatureXml, string ManifestXml, string TargetAssemblyPath, string FeatureName, string FeatureId)
        {
            AppDomainSetup domaininfo = new AppDomainSetup();
            AppDomain newDomain = null;

            if (!File.Exists(TargetAssemblyPath))
                return new string[] { FeatureXml, ManifestXml };


            try
            {
                // Create application domain setup information for new application domain.
                domaininfo.ApplicationBase = Path.GetDirectoryName(TargetAssemblyPath);
                domaininfo.ApplicationName = "SPVisualDev_appl_" + Guid.NewGuid().ToString("N");

                // Create appdomain.
                newDomain = AppDomain.CreateDomain("SPVisualDev_appdomain_" + Guid.NewGuid().ToString("N"), null, domaininfo);

                // Load an assembly into the new application domain.
                Worker w = (Worker)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().GetName().FullName, "SPVisualDev.Worker");
                
                string[] ret = w.GenerateEventReceiverXML(
                    FeatureXml,
                    ManifestXml,
                    TargetAssemblyPath,
                    FeatureName,
                    FeatureId);

                if (ret == null)
                {
                    MessageBox.Show("The assembly contains event receivers but is not signed with a strong key.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return new string[] { FeatureXml, ManifestXml };
                }
                else
                {
                    return ret;
                }
            }
            catch (ReflectionTypeLoadException rtle)
            {
                string dump = string.Empty;
                foreach (Exception ex in rtle.LoaderExceptions)
                    dump += ex.Message + "\n";

                MessageBox.Show("Error occured while loading types. \n\n" + dump + "\n\n" + rtle.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }
            finally
            {
                if (newDomain != null)
                    AppDomain.Unload(newDomain);
            }
        }

        
        public static bool ShouldIgnoreFile(string FileName, string IgnoreFileExtensionsString)
        {
            if (IgnoreFileExtensionsString == null)
                IgnoreFileExtensionsString = C_IGNORE_FILE_TYPE_ON_PUSH_DOWN;

            if (IgnoreFileExtensionsString == string.Empty || Path.GetExtension(FileName) == string.Empty)
                return false;

            string[] arr = IgnoreFileExtensionsString.Split(';');
            string result = Array.Find<string>(arr, delegate(string extension) {

                if (string.IsNullOrEmpty(extension))
                    return false;

                if (extension.ToLower().Trim() == Path.GetExtension(FileName).ToLower().Trim())
                    return true;
                else
                    return false;
            });

            return (result != null);
        }

        //Not longer in use
        /*
        public static void SetUserOptionsFileKey(Project project, string key, string value)
        {
            string proj_file = project.Properties.Item("LocalPath").Value.ToString() + project.Properties.Item("FileName").Value.ToString();
            string proj_user_file = proj_file + ".user";
            if (!File.Exists(proj_user_file))
                throw new Exception("User options file not found.");

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(proj_user_file);

            XmlNamespaceManager xml_ns_manager = new XmlNamespaceManager(xmldoc.NameTable);
            xml_ns_manager.AddNamespace("dev", "http://schemas.microsoft.com/developer/msbuild/2003");

            XmlNode xn_web_proj_properties = xmldoc.SelectSingleNode("/dev:Project/dev:ProjectExtensions/dev:VisualStudio/FlavorProperties/WebProjectProperties", xml_ns_manager);
            if (xn_web_proj_properties == null)
                xn_web_proj_properties = xmldoc.SelectSingleNode("/dev:Project/dev:ProjectExtensions/dev:VisualStudio/dev:FlavorProperties/dev:WebProjectProperties", xml_ns_manager);

            if (xn_web_proj_properties == null)
                throw new Exception("Can not find XML path in user options file.");

            XmlNode xn = xn_web_proj_properties.SelectSingleNode(key, xml_ns_manager);
            if (xn == null)
                xn = xn_web_proj_properties.SelectSingleNode("dev:" + key, xml_ns_manager);

            if (xn == null)
                throw new Exception("Key can not be found.");

            xn.InnerText = value;

            xmldoc.Save(proj_user_file);
        }

        public static string GetUserOptionsFileKey(Project project, string key)
        {
            string proj_file = project.Properties.Item("LocalPath").Value.ToString() + project.Properties.Item("FileName").Value.ToString();
            string proj_user_file = proj_file + ".user";
            if (!File.Exists(proj_user_file))
                throw new Exception("User options file not found.");

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(proj_user_file);

            XmlNamespaceManager xml_ns_manager = new XmlNamespaceManager(xmldoc.NameTable);
            xml_ns_manager.AddNamespace("dev", "http://schemas.microsoft.com/developer/msbuild/2003");

            XmlNode xn_web_proj_properties = xmldoc.SelectSingleNode("/dev:Project/dev:ProjectExtensions/dev:VisualStudio/FlavorProperties/WebProjectProperties", xml_ns_manager);
            if (xn_web_proj_properties == null)
                xn_web_proj_properties = xmldoc.SelectSingleNode("/dev:Project/dev:ProjectExtensions/dev:VisualStudio/dev:FlavorProperties/dev:WebProjectProperties", xml_ns_manager);

            if (xn_web_proj_properties == null)
                throw new Exception("Can not find XML path in user options file.");

            XmlNode xn = xn_web_proj_properties.SelectSingleNode(key, xml_ns_manager);
            if (xn == null)
                xn = xn_web_proj_properties.SelectSingleNode("dev:" + key, xml_ns_manager);

            if (xn == null)
                throw new Exception("Key can not be found.");

            return xn.InnerText;
        }
        */

        public static string FilterXmlString(string Xml)
        {
            return Xml.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
        }

        public static void SetXmlAttribute(XmlElement element, string AttributeName, string Value)
        {
            SetXmlAttribute(element, AttributeName, Value, false);
        }
        public static void SetXmlAttribute(XmlElement element, string AttributeName, string Value, bool IgnoreIfEmptyAndNotExists)
        {
            XmlAttribute attribute = null;
            foreach (XmlAttribute a in element.Attributes)
            {
                if (string.Compare(a.Name, AttributeName, true) == 0)
                {
                    attribute = a;
                    break;
                }
            }

            if (attribute == null)
            {
                if (!IgnoreIfEmptyAndNotExists || !string.IsNullOrEmpty(Value))
                    element.SetAttribute(AttributeName, Value);
            }
            else
            {
                attribute.Value = Value;
            }
        }
        public static void SetXmlAttributeIgnoreIfValueMatches(XmlElement element, string AttributeName, string Value)
        {
            SetXmlAttributeIgnoreIfValueMatches(element, AttributeName, Value, false);
        }
        public static void SetXmlAttributeIgnoreIfValueMatches(XmlElement element, string AttributeName, string Value, bool IgnoreIfEmptyAndNotExists)
        {
            XmlAttribute attribute = null;
            foreach (XmlAttribute a in element.Attributes)
            {
                if (string.Compare(a.Name, AttributeName, true) == 0)
                {
                    attribute = a;
                    break;
                }
            }

            if (attribute == null)
            {
                if (!IgnoreIfEmptyAndNotExists || !string.IsNullOrEmpty(Value))
                    element.SetAttribute(AttributeName, Value);
            }
            else
            {
                if (string.Compare(Value, attribute.Value, true) != 0)
                    attribute.Value = Value;
            }
        }
        
        public static string GetXmlAttribute(XmlElement element, string AttributeName)
        {
            string ret = string.Empty;
            foreach (XmlAttribute attribute in element.Attributes)
            {
                if (string.Compare(attribute.Name, AttributeName, true) == 0)
                {
                    ret = attribute.Value;
                    break;
                }
            }

            return ret;
        }

        public static Guid GetFeatureIdForBuiltInListType(int ListType)
        {
            Guid ret;
            switch (ListType)
            {
                case 100:
                    ret = new Guid("00BFEA71-DE22-43B2-A848-C05709900100");
                    break;
                case 101:
                    ret = new Guid("00BFEA71-E717-4E80-AA17-D0C71B360101");
                    break;
                case 102:
                    ret = new Guid("00BFEA71-EB8A-40B1-80C7-506BE7590102");
                    break;
                case 103:
                    ret = new Guid("00BFEA71-2062-426C-90BF-714C59600103");
                    break;
                case 104:
                    ret = new Guid("00BFEA71-D1CE-42de-9C63-A44004CE0104");
                    break;
                case 105:
                    ret = new Guid("00BFEA71-7E6D-4186-9BA8-C047AC750105");
                    break;
                case 106:
                    ret = new Guid("00BFEA71-EC85-4903-972D-EBE475780106");
                    break;
                case 107:
                    ret = new Guid("00BFEA71-A83E-497E-9BA0-7A5C597D0107");
                    break;
                case 108:
                    ret = new Guid("00BFEA71-6A49-43FA-B535-D15C05500108");
                    break;
                case 109:
                    ret = new Guid("00BFEA71-52D4-45B3-B544-B1C71B620109");
                    break;
                case 110:
                    ret = new Guid("00BFEA71-F381-423D-B9D1-DA7A54C50110");
                    break;
                case 115:
                    ret = new Guid("00BFEA71-1E1D-4562-B56A-F05371BB0115");
                    break;
                case 118:
                    ret = new Guid("00BFEA71-2D77-4A75-9FCA-76516689E21A");
                    break;
                case 119:
                    ret = new Guid("00BFEA71-C796-4402-9F2F-0EB9A6E71B18");
                    break;
                case 120:
                    ret = new Guid("00BFEA71-3A1D-41D3-A0EE-651D11570120");
                    break;
                default:
                    ret = Guid.Empty;
                    break;
            }

            return ret;
        }

        public static void SetUserRegistryParam(string Parameter, string Value)
        {
            Registry.SetValue("HKEY_CURRENT_USER\\Software\\SPVisualDev", Parameter, Value);
        }

        public static string GetUserRegistryParam(string Parameter, bool bReturnNullIfNotExists)
        {
            string ret = Registry.GetValue("HKEY_CURRENT_USER\\Software\\SPVisualDev", Parameter, null) as string;

            if (ret == null && !bReturnNullIfNotExists)
                ret = string.Empty;
            
            return ret;
        }

        public static bool CheckIf32bitOn64()
        {
            //SPFarm.Local return null if trying to call 64 bit sharepoint API from 32 bit. This happens in VS 2008 because it is 32 bit.
            return (SPFarm.Local == null);
        }

        public static bool CheckIfUserHasSuffAdminPrivOnFarm(bool bShowMessage)
        {
            try
            {
                SPFarm farm = SPFarm.Local;
                if (farm == null)
                    throw new ArgumentNullException();

                if (!farm.CurrentUserIsAdministrator())
                    throw new Exception();

                return true;
            }
            catch (ArgumentNullException)
            {
                if (bShowMessage)
                {
                    MessageBox.Show("This feature is not supported on 64 bit SharePoint installation.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
                else
                {
                    throw;
                }

            }
            catch
            {
                if (bShowMessage)
                {
                    if (Environment.OSVersion.Version.Major > 5)
                        MessageBox.Show("Current user doesn't have administrator privileges on the local sharepoint farm and / or no access to the configuration database. If the system has UAC turned on, please turn it off or try run this application as administrator.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    else
                        MessageBox.Show("Current user doesn't have administrator privileges on the local sharepoint farm and / or no access to the configuration database.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return false;
            }
        }

        public static string GetTargetBuildAssemblyName(Project project, bool suppressErrorMsg)
        {
            AppDomainSetup domaininfo = new AppDomainSetup();
            AppDomain newDomain = null;

            try
            {
                // Create application domain setup information for new application domain.
                domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
                domaininfo.ApplicationName = "SPVisualDev_appl_" + Guid.NewGuid().ToString("N");

                // Create appdomain.
                newDomain = AppDomain.CreateDomain("SPVisualDev_appdomain_" + Guid.NewGuid().ToString("N"), null, domaininfo);

                // Load an assembly into the new application domain.
                Worker w = (Worker)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().GetName().FullName, "SPVisualDev.Worker");
                string asm_name = w.GetTargetAssemblyName(GetTargetPath(project));

                return asm_name;
            }
            catch (Exception ex)
            {
                if (!suppressErrorMsg)
                    MessageBox.Show("Unable to fetch assembly name information. " + ex.ToString(), "Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);

                throw;
            }
            finally
            {
                if (newDomain != null)
                    AppDomain.Unload(newDomain);
            }
        }

        public static void MakeEntityClasses(ProjectItem project_item, bool isEntityFile)
        {
            string filteredName;
            ProjectItem feature_folder_item;

            if (isEntityFile)
            {
                filteredName = project_item.Name;
                feature_folder_item = project_item.Collection.Parent as ProjectItem;
            }
            else
            {
                filteredName = Common.FilterIllegalCharsInFileName(project_item.Name);
                feature_folder_item = project_item;
            }

            string Namespace = project_item.ContainingProject.Properties.Item("RootNamespace").Value.ToString() + "." + filteredName;

            bool bNew = false;
            ProjectItem item = null;
            TextDocument text_document = null;

            if (!isEntityFile)
            {
                try
                {
                    item = project_item.ProjectItems.Item(filteredName + ".cs");
                }
                catch
                {
                    DTE _dte = project_item.DTE;
                    string s = ((EnvDTE80.Solution2)_dte.Solution).GetProjectItemTemplate("Class.zip", "CSharp");
                    feature_folder_item.ProjectItems.AddFromTemplate(s, filteredName + ".cs");

                    item = feature_folder_item.ProjectItems.Item(filteredName + ".cs");
                    text_document = (TextDocument)item.Document.Object("TextDocument");
                    bNew = true;
                }
            }
            else
            {
                item = project_item;
            }

            /*
             * Find field entity classes in current assembly
            */
            AppDomainSetup domaininfo = new AppDomainSetup();
            AppDomain newDomain = null;

            ProjectItem feature_xml = feature_folder_item.ProjectItems.Item("Feature.xml");
            if (feature_xml == null)
                feature_xml = feature_folder_item.ProjectItems.Item("feature.xml");

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(Common.GetProjectItemPath(feature_xml));

            int xml_hash_code = xmldoc.OuterXml.GetHashCode();

            bool bFeatureEventReceiverIsValid = false;
            Dictionary<Guid, string> types;
            try
            {
                // Create application domain setup information for new application domain.
                domaininfo.ApplicationBase = Path.GetDirectoryName(GetTargetPath(feature_folder_item.ContainingProject));
                domaininfo.ApplicationName = "SPVisualDev_appl_" + Guid.NewGuid().ToString("N");

                // Create appdomain.
                newDomain = AppDomain.CreateDomain("SPVisualDev_appdomain_" + Guid.NewGuid().ToString("N"), null, domaininfo);

                // Load an assembly into the new application domain.
                Worker w = (Worker)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().GetName().FullName, "SPVisualDev.Worker");
                types = w.GetWSSFieldsInAssembly(GetTargetPath(project_item.ContainingProject), false);

                if (!string.IsNullOrEmpty(xmldoc.DocumentElement.GetAttribute("ReceiverAssembly")))
                {
                    if (xmldoc.DocumentElement.GetAttribute("ReceiverAssembly").Replace(" ", "").ToLower() != C_SPDEVEXTENSIONS_ASSEMBLY_NAME.Replace(" ", "").ToLower())
                    {
                        if (xmldoc.DocumentElement.GetAttribute("ReceiverClass") != string.Empty)
                        {
                            bFeatureEventReceiverIsValid = w.HasValidFeatureReceiverBase(xmldoc.DocumentElement.GetAttribute("ReceiverAssembly"), xmldoc.DocumentElement.GetAttribute("ReceiverClass"));
                        }
                    }
                    else
                    {
                        bFeatureEventReceiverIsValid = true;
                    }

                    if (!bFeatureEventReceiverIsValid)
                    {
                        if (MessageBox.Show("The feature definition already contains an event receiver. To add special features provided by SPDevExtensions, you must either replace the event receiver with the one provided by SPDevExtensions, or you can inherit from a special receiver base. Do you want to replace the event receiver?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                        {
                            xmldoc.DocumentElement.SetAttribute("ReceiverAssembly", Common.C_SPDEVEXTENSIONS_ASSEMBLY_NAME);
                            xmldoc.DocumentElement.SetAttribute("ReceiverClass", Common.C_SPDEVEXTENSIONS_WSSTES_FEATURE_RECEIVER_CLASS);
                        }
                    }

                }
                else
                {
                    if (MessageBox.Show("The feature definition has no event receiver. To add special features provided by SPDevExtensions, you must add one provided by SPDevExtensions, or you can inherit from a special receiver base class. Do you want to add it now?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        xmldoc.DocumentElement.SetAttribute("ReceiverAssembly", Common.C_SPDEVEXTENSIONS_ASSEMBLY_NAME);
                        xmldoc.DocumentElement.SetAttribute("ReceiverClass", Common.C_SPDEVEXTENSIONS_WSSTES_FEATURE_RECEIVER_CLASS);
                    }
                }

            }
            catch (ReflectionTypeLoadException rtle)
            {
                string dump = string.Empty;
                foreach (Exception ex in rtle.LoaderExceptions)
                    dump += ex.Message + "\n";

                MessageBox.Show("Error occured while loading types. \n\n" + dump + "\n\n" + rtle.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            finally
            {
                if (newDomain != null)
                    AppDomain.Unload(newDomain);
            }

            
            WSSTypeImporter type_importer = new WSSTypeImporter();
            
            type_importer.WSSFieldsInAssembly = types;
            type_importer.CodeFile = (EnvDTE80.FileCodeModel2)item.FileCodeModel;

            type_importer.MakeEntityClassesFromFeatureDef(
                    GetProjectItemPath(feature_folder_item),
                    Namespace,
                    bNew
                );


            if (item != null && bNew)
            {
                try
                {
                    VSLangProj80.VSProject2 vsproj2 = (VSLangProj80.VSProject2)item.ContainingProject.Object;
                    vsproj2.References.Add("SPDevExtensions.dll");

                    string s = Common.GetProjectGlobalConfigKey(project_item.ContainingProject, "IncludedAssemblies");
                    if (s != null)
                    {
                        if (s == "")
                            s = "SPDevExtensions";
                        else if (s.IndexOf("SPDevExtensions") == -1)
                            s += ";SPDevExtensions";
                    }
                    else
                    {
                        if (s == "")
                            s += "SPDevExtensions";
                        else
                            s += ";SPDevExtensions";
                    }
                    Common.SetProjectGlobalConfigKey(project_item.ContainingProject, "IncludedAssemblies", s, true);
                }
                catch(Exception ex)
                {
                    MessageBox.Show("Failed to add reference to SPDevExtensions assembly. " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                item.Save(item.Name);
            }




            XmlNodeList nl = xmldoc.DocumentElement.GetElementsByTagName("Properties", C_MS_SHAREPOINT_XMLNS);
            XmlElement el;
            if (nl.Count == 0)
            {
                el = xmldoc.CreateElement("Properties", C_MS_SHAREPOINT_XMLNS);
                xmldoc.DocumentElement.AppendChild(el);
            }
            else
            {
                el = nl[0] as XmlElement;
            }

            XmlElement prop = null;
            foreach (XmlNode n in el.ChildNodes)
            {
                if (n.NodeType == XmlNodeType.Element)
                {
                    if (n.Name == "Property")
                    {
                        if (((XmlElement)n).GetAttribute("Key") == C_SPDEVEXTENSIONS_FEATURE_PROPERTY_NAME)
                        {
                            prop = n as XmlElement;
                            break;
                        }
                    }
                }
            }

            if (prop == null)
            {
                prop = xmldoc.CreateElement("Property", C_MS_SHAREPOINT_XMLNS);
                prop.SetAttribute("Key", C_SPDEVEXTENSIONS_FEATURE_PROPERTY_NAME);
                prop.SetAttribute("Value", Common.GetTargetBuildAssemblyName(project_item.ContainingProject, true));

                el.AppendChild(xmldoc.CreateWhitespace("\r\n\t\t\t"));
                el.AppendChild(prop);
                el.AppendChild(xmldoc.CreateWhitespace("\r\n"));
            }

            if (xmldoc.OuterXml.GetHashCode() == xml_hash_code)
                return;

            //SCC handle
            if (Common.CheckOutItemFromSCC(feature_xml))
                Common.SaveXmlIndented(ref xmldoc, Common.GetProjectItemPath(feature_xml));
        }

        public static bool CheckIfSpecialProject(Project Proj)
        {
            try
            {
                string id = Common.GetProjectGlobalConfigKey(Proj, Common.C_PROJECT_ID_VAR_NAME);
                return (!string.IsNullOrEmpty(id));
            }
            catch
            {
                return false;
            }
        }

        public static bool HasUnsavedOpenedDocuments(EnvDTE80.DTE2 dte)
        {
            bool bFlag = false;

            foreach (Document doc in dte.Documents)
            {
                ProjectItem item = doc.ProjectItem;
                if (item != null)
                {
                    if (item.get_IsOpen(Constants.vsViewKindAny))
                    {
                        if (item.IsDirty)
                        {
                            bFlag = true;
                            break;
                        }
                    }
                }
            }

            return bFlag;
        }

        private void ReplaceTextInItems(string SearchText, string ReplaceText, ProjectItem StartFolder, bool Recursive)
        {
            foreach (ProjectItem item in StartFolder.ProjectItems)
            {
                
            }
        }

        public static void ReplaceParametersInFile(string path, Hashtable replacementParameters)
        {
            string content;

            using (StreamReader sr = new StreamReader(path))
            {
                content = sr.ReadToEnd();
            }

            foreach (DictionaryEntry de in replacementParameters)
            {
                content = content.Replace(de.Key.ToString(), de.Value.ToString());
            }

            using (StreamWriter sw = new StreamWriter(path, false))
            {
                sw.Write(content);
            }
        }

        public static string GetProjectItemPath(ProjectItem Item)
        {
            return GetProjectItemPath(Item, false);
        }

        public static string GetProjectItemPath(ProjectItem Item, bool RelativeToProject)
        {
            string path = Item.Properties.Item("FullPath").Value.ToString();

            if (RelativeToProject)
            {
                string proj_path = Item.ContainingProject.Properties.Item("LocalPath").Value.ToString();
                if (proj_path.EndsWith("\\"))
                    path = path.Substring(proj_path.Length);
                else
                    path = path.Substring(proj_path.Length - 1);
            }

            return (path.EndsWith("\\")) ? path.Substring(0, path.Length - 1) : path;
        }

        public static Project GetProjectByName(Projects projects, string name)
        {
            foreach(Project p in projects)
            {
                if (p.Name == name)
                    return p;
            }

            return null;
        }

        public static string GetSafeName(string Folder, string SuggestedName)
        {
            int i = 0;

            string Suggested_name_without_extension = Path.GetFileNameWithoutExtension(SuggestedName);
            string Suggested_name_extension = Path.GetExtension(SuggestedName);
            
            SuggestedName = Suggested_name_without_extension + Suggested_name_extension;
            while (File.Exists(Folder + "\\" + SuggestedName) || Directory.Exists(Folder + "\\" + SuggestedName))
            {
                i++;
                SuggestedName = Suggested_name_without_extension + i.ToString() + Suggested_name_extension;
            }

            return SuggestedName;
        }

        public static string FilterIllegalCharsInFileName(string FileName)
        {
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"[^a-zA-Z0-9\-]");
            return regex.Replace(FileName, "_");
        }

        public static bool CheckOutItemFromSCC(ProjectItem item)
        {
            try
            {
                //Check source control
                EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)item.DTE;
                bool b = dte2.SourceControl.IsItemUnderSCC(Common.GetProjectItemPath(item));
                if (b)
                {
                    if (!dte2.SourceControl.IsItemCheckedOut(Common.GetProjectItemPath(item)))
                    {
                        if (MessageBox.Show("Item '" + GetProjectItemPath(item, true) + "' will be checked out. Do you want to continue?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            dte2.SourceControl.CheckOutItem(Common.GetProjectItemPath(item));
                        }
                        else
                        {
                            MessageBox.Show("Operation cancelled!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            return false;
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error checking out item " + item.Name + ". Info: " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static string GetTargetPath(Project proj)
        {
            string project_path = proj.Properties.Item("LocalPath").Value.ToString();
            string target_file_name = proj.Properties.Item("OutputFileName").Value.ToString();
            string output_path = proj.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();

            return project_path + output_path + target_file_name;
        }

        public static ProjectItem GetEventReceiversFolder(Project project)
        {
            ProjectItem item = null;

            string[] arr = C_PROJECT_EVENT_RECEIVER_CODE_PATH.Split('\\');
            for (int i = 0; i < arr.Length; i++)
            {
                if (item == null)
                    item = project.ProjectItems.Item(arr[0]);
                else
                    item = item.ProjectItems.Item(arr[i]);
            }

            return item;
        }

        public static ProjectItem CreateProjectItemPath(Project project, string path)
        {
            string[] arr = path.Split('\\');

            ProjectItem item;
            try
            {
                item = project.ProjectItems.Item(arr[0]);
            }
            catch
            {
                item = project.ProjectItems.AddFolder(arr[0], Constants.vsProjectItemKindPhysicalFolder);
            }

            for (int i = 1; i < arr.Length; i++)
            {
                try
                {
                    item = item.ProjectItems.Item(arr[i]);
                }
                catch
                {
                    item = item.ProjectItems.AddFolder(arr[i], Constants.vsProjectItemKindPhysicalFolder);
                }
            }

            return item;
        }

        public static string GetInstallationKey(string key, bool bThrowExceptionIfNotExists)
        {
            string ret = null;
            try
            {
                RegistryKey regkey = Registry.LocalMachine.OpenSubKey("Software\\SPVisualDev", false);
                if (regkey == null)
                    regkey = Registry.CurrentUser.OpenSubKey("Software\\SPVisualDev", false);

                if (regkey == null)
                {
                    throw new Exception("Required registry key is not present.");
                }
                else
                {
                    ret = regkey.GetValue(key).ToString();
                }
            }
            catch 
            {
                if (bThrowExceptionIfNotExists)
                    throw;
            }

            return ret;
        }

        public static string GetSharePointInstallPath()
        {
            string path = null;
            
            //Try by getting path by looking in the registry.
            try
            {
                path = (string)Registry.GetValue("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Shared Tools\\Web Server Extensions\\12.0", "Location", "");
            }
            catch { }

            //If it didn't work, try find a standard feature definition.
            try
            {
                if (!CheckIf32bitOn64())
                {
                    if (string.IsNullOrEmpty(path))
                    {
                        SPFeatureDefinition def = SPFarm.Local.FeatureDefinitions["fields"];
                        DirectoryInfo info = Directory.GetParent(def.RootDirectory);
                        path = info.Parent.Parent.FullName;
                    }
                }
            }
            catch { }


            //Still no value? Try environment variables.
            try
            {
                if (string.IsNullOrEmpty(path))
                {
                    string probe_path = @"\Microsoft Shared\web server extensions\12\BIN\STSADM.exe";
                    path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + probe_path;
                    if (string.IsNullOrEmpty(path) || !File.Exists(path))
                        path = Environment.GetEnvironmentVariable("CommonProgramW6432") + @"\Microsoft Shared\web server extensions\12";
                    else
                        path = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + @"\Microsoft Shared\web server extensions\12";
                }
            }
            catch { }

            //If the directory is not valid, throw an error.
            if (!Directory.Exists(path))
                throw new Exception("Can not find SharePoint 12 hive on system.");

            if (!string.IsNullOrEmpty(path))
                if (path.EndsWith("\\"))
                    path = path.Substring(0, path.Length - 1);

            return path;
        }

        public static bool CheckIfFileExistsIn12Hive(Project project, string ItemFilePath)
        {
            string proj_12_hive = Path.GetDirectoryName(project.FullName) + "\\12";
            string system_12_hive = GetSharePointInstallPath();
            string relative_path_to_12_hive = ItemFilePath.Substring(proj_12_hive.Length + 1);
            string dest = system_12_hive + "\\" + relative_path_to_12_hive;

            if (File.Exists(dest))
                return true;
            else if (Directory.Exists(dest))
                return true;
            else
                return false;
        }

        public static bool CheckIfFileExistsIn12Hive(ProjectItem Item)
        {
            string path = Common.GetProjectItemPath(Item);
            string proj_12_hive = Path.GetDirectoryName(Item.ContainingProject.FullName) + "\\12";
            string system_12_hive = GetSharePointInstallPath();

            string relative_path_to_12_hive = path.Substring(proj_12_hive.Length + 1);

            string dest = system_12_hive + "\\" + relative_path_to_12_hive;

            if (Item.Kind == Constants.vsProjectItemKindPhysicalFile)
                return File.Exists(dest);
            else if (Item.Kind == Constants.vsProjectItemKindPhysicalFolder)
                return Directory.Exists(dest);
            else
                return false;
        }

        public static bool CheckIfFileExistsIn12Hive(ProjectItem NewItem, string ItemName)
        {
            ProjectItem parent_item = (ProjectItem)NewItem.Collection.Parent;

            string path = Common.GetProjectItemPath(parent_item) + "\\" + ItemName;
            string proj_12_hive = Path.GetDirectoryName(parent_item.ContainingProject.FullName) + "\\12";
            string system_12_hive = GetSharePointInstallPath();
            string relative_path_to_12_hive = path.Substring(proj_12_hive.Length + 1);
            string dest = system_12_hive + "\\" + relative_path_to_12_hive;

            if (NewItem.Kind == Constants.vsProjectItemKindPhysicalFile)
                return File.Exists(dest);
            else if (NewItem.Kind == Constants.vsProjectItemKindPhysicalFolder)
                return Directory.Exists(dest);
            else
                return false;
        }

        public static bool CheckIfInsideFeaturesFolder(ProjectItem Item)
        {
            ProjectItem parent = (ProjectItem)Item.Collection.Parent;
            while (parent != null && parent.Name.ToLower() != "features")
            {
                try
                {
                    parent = (ProjectItem)parent.Collection.Parent;
                }
                catch
                {
                    return false;
                }
            }

            return (parent != null);
        }

        public static void SaveXmlIndented(ref XmlDocument xdoc, string path)
        {
            XmlWriter writer = null;
            try
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.NewLineHandling = NewLineHandling.None;
                settings.NewLineOnAttributes = true;
                settings.IndentChars = "\t";
                settings.Indent = true;

                writer = XmlTextWriter.Create(path, settings);
                //writer.Formatting = Formatting.Indented;



                //xdoc.PreserveWhitespace = true;
                xdoc.Save(writer);
            }
            finally
            {
                if (writer != null)
                    writer.Close();
            }
        }

        public static string GetProjectGlobalConfigKey(Project project, string Key)
        {
            if (project.Globals.get_VariableExists(C_GLOBAL_CONFIG_KEY_PREFIX + Key))
            {
                string ret = project.Globals[C_GLOBAL_CONFIG_KEY_PREFIX + Key] as string;
                if (string.IsNullOrEmpty(ret))
                    return string.Empty;
                else
                    return ret;
            }
            else
                return string.Empty;
        }

        public static void SetProjectGlobalConfigKey(Project project, string Key, string Value, bool Persist)
        {
            project.Globals[C_GLOBAL_CONFIG_KEY_PREFIX + Key] = Value;
            project.Globals.set_VariablePersists(C_GLOBAL_CONFIG_KEY_PREFIX + Key, Persist);
        }

        public static string GetUserSettingsKey(Project proj, string Key)
        {
            XmlDocument xdoc = new XmlDocument();
            string settings_file = proj.Properties.Item("LocalPath").Value.ToString() + Common.C_SETTINGS_FILE;

            if (!File.Exists(settings_file))
            {
                xdoc.LoadXml("<Settings></Settings>");
                xdoc.Save(settings_file);
            }
            else
            {
                xdoc.Load(settings_file);
            }

            XmlNode xn = xdoc.DocumentElement.SelectSingleNode(Key);
            if (xn != null)
                return xn.InnerText;
            else
                return null;
        }

        public static void SetUserSettingsKey(Project proj, string Key, string Value)
        {
            XmlDocument xdoc = new XmlDocument();
            string settings_file = proj.Properties.Item("LocalPath").Value.ToString() + Common.C_SETTINGS_FILE;

            if (!File.Exists(settings_file))
            {
                xdoc.LoadXml("<Settings></Settings>");
            }
            else
            {
                xdoc.Load(settings_file);
            }

            XmlNode xn = xdoc.DocumentElement.SelectSingleNode(Key);
            if (xn != null)
                xn.InnerText = Value;
            else
            {
                XmlElement el = xdoc.CreateElement(Key);
                el.InnerText = Value;
                xdoc.DocumentElement.AppendChild(el);
            }

            xdoc.Save(settings_file);
        }

        public static void SetNamespaceInCodeFile(ref ProjectItem Item, string Namespace)
        {
            EnvDTE80.FileCodeModel2 file = (EnvDTE80.FileCodeModel2)Item.FileCodeModel;
            foreach (CodeElement element in file.CodeElements)
            {
                if (element is CodeNamespace)
                {
                    EditPoint start = element.StartPoint.CreateEditPoint();
                    start.ReplaceText(start.LineLength, "namespace " + Namespace, (int)vsEPReplaceTextOptions.vsEPReplaceTextAutoformat);

                    return;

                }
            }
        }

        public static ProjectItem AddNewCulture(string ResourceFile, string cultureInfo, Project project, ProjectItem FeatureNode)
        {
            bool isLocalResource = (FeatureNode != null);
            ProjectItem resource_folder = null;

            string res_file_name = ResourceFile;
            if (!string.IsNullOrEmpty(cultureInfo))
                res_file_name += "." + cultureInfo;
            res_file_name += ".resx";

            if (isLocalResource)
            {
                resource_folder = Common.CreateProjectItemPath(project, "12\\TEMPLATE\\Features\\" + FeatureNode.Name + "\\Resources");

                try
                {
                    ProjectItem resources = resource_folder.ProjectItems.Item(res_file_name);
                    if (resources != null)
                    {
                        throw new Exception("A resource file with the same name exists already. Operation aborted.");
                    }
                }
                catch { }
            }
            else
            {
                resource_folder = Common.CreateProjectItemPath(project, "12\\Resources");
                try
                {
                    ProjectItem resources = resource_folder.ProjectItems.Item(res_file_name);
                    if (resources != null)
                    {
                        throw new Exception("A resource file with the same name exists already. Operation aborted.");
                    }
                }
                catch { }
            }

            if (resource_folder != null)
            {
                string template_path = ((EnvDTE80.Solution2)project.DTE.Solution).GetProjectItemTemplate("Resource.zip", "csproj");
                resource_folder.ProjectItems.AddFromTemplate(template_path, res_file_name);

                try
                {
                    resource_folder.ProjectItems.Item(res_file_name).Document.Close(vsSaveChanges.vsSaveChangesYes);
                }
                catch { }

                return resource_folder.ProjectItems.Item(res_file_name);
            }
            else
            {
                return null;
            }

        }


    }


}

